Cloudflare Workers 仮想モジュールビルド失敗問題
from ✅売り子が交代したときにデータを引き継げる機能
Claude Sonnet 4.icon
🔍 問題の概要
根本原因: Cloudflare Workersのビルドプロセス(Wrangler)が静的解析で全てのインポート文を解決しようとするため、React Routerの開発用仮想モジュールvirtual:react-router/server-build がエラーを引き起こしていました。
エラーメッセージ:
Could not resolve "virtual:react-router/server-build"
📋 試行した解決策
1. 環境判定による条件分岐 ❌
modeや環境変数による条件分岐を試行
問題: Wranglerがビルド時に全インポート文を静的解析するため効果なし
2. 文字列連結による回避 ❌
仮想モジュールパスを動的に生成して静的解析を回避
問題: Viteが依然として仮想モジュールを認識してエラー
3. try-catch による動的解決 ❌
実ビルドファイルを優先し、失敗時に仮想モジュールを使用
問題: ビルド時に仮想モジュールインポートが存在するだけでエラー
4. ファイル分離アプローチ ❌
開発用・本番用の別ファイルを作成し動的インポート
問題: 複雑な非同期処理でroutes undefinedエラーが発生
✅ 採用した暫定解決策
ファイル切り替え方式
構成:
workers/app.ts: 本番環境用(実ビルドファイルのみ)
workers/app.dev.ts: 開発環境用(仮想モジュール使用)
スクリプト:
npm run dev: 開発時にapp.dev.tsをapp.tsにコピーして開発サーバー起動
npm run dev:restore: 元のapp.ts(本番版)に復元
メリット:
✅ 開発環境で仮想モジュールが正常動作
✅ Cloudflareビルドで仮想モジュールエラーを完全回避
✅ 全てのローカルテスト(build, typecheck, lint)が通る
デメリット:
❌ ファイルコピーによる切り替えが美しくない
❌ 開発者が手動でファイル状態を管理する必要
🚀 今後の課題・改善案
1. より洗練された解決策の検討
A. Viteプラグインアプローチ
カスタムViteプラグインで環境に応じた仮想モジュール解決
ビルド時の条件分岐をより適切に処理
B. Wrangler設定による外部化
wrangler.jsoncでより詳細なモジュール解決設定
仮想モジュールの完全な外部化
C. React Router設定の見直し
React Routerの設定で仮想モジュールを使わない方法
別のサーバービルド取得方法の採用
2. 開発体験の改善
A. 自動化の強化
npm run dev終了時の自動復元
Git hooks による状態管理
B. ドキュメント整備
開発者向けガイドライン作成
ファイル切り替えのベストプラクティス
3. 長期的な解決策
A. React Router v7対応
新しいバージョンでの仮想モジュール扱いの改善待ち
アップグレード時の移行計画
B. 代替フレームワークの検討
Cloudflare Workers により適したフレームワークの調査
移行コストとメリットの評価
📊 現在の状態
開発環境: ✅ 正常動作(npm run dev使用)
ローカルビルド: ✅ 正常動作
Cloudflareビルド: 🔄 テスト中(最新プッシュ後)
型チェック・Lint: ✅ 全て通過
🎯 次のアクション
1. 即座に: Cloudflareビルド結果の確認
2. 短期: より美しい解決策の研究・実装
3. 中期: React Router更新やフレームワーク見直しの検討
4. 長期: 開発体験の最適化とドキュメント整備
現在の暫定解決策は機能的には完璧ですが、開発体験の向上のため、より洗練されたアプローチを継続的に模索していく必要があります。
基素.icon
「ファイル切り替え方式」の保守性は明らかに著しく低い。許容できないのでビルドプロセスがおかしいだろうと判断
書き直すための調査をさせた
Claude Sonnet 4.icon
📋 調査結果まとめ
1. Cloudflare公式のReact Router v7対応状況
2025年4月にReact Router v7のCloudflare Workers対応がGA(一般提供開始)
Cloudflare Vite Plugin v1.0が正式リリース済み
npm create cloudflare@latest my-app -- --framework=react-routerでテンプレート作成可能
2. Wranglerの外部モジュール機能
find_additional_modules: trueでファイルツリーを走査
rules設定で特定ファイルを外部モジュールとして扱い可能
esbuildにバンドルせずランタイムで利用可能
3. 仮想モジュールの技術的背景
Viteではvirtual:プレフィックスが慣例
esbuildプラグインでonResolve/onLoadフックを使用
カスタムビルドプロセスで仮想モジュールを実モジュールに変換可能
🎯 提案する解決策(優先順位順)
解決策1: Cloudflare公式テンプレートへの移行 ⭐⭐⭐
概要: 最新のCloudflare公式React Router v7テンプレートを使用
新しいプロジェクトを作成してコードを移行
仮想モジュール問題が根本的に解決済み
長期的なサポートが保証
実装:
1. npm create cloudflare@latest hampu-new -- --framework=react-router
2. 既存コードを新プロジェクトに移行
3. D1、DO、cronなどの設定を移行
解決策2: wrangler.jsonc外部モジュール設定 ⭐⭐
概要: find_additional_modulesとrulesを使って仮想モジュールを外部化
code:json
{
"find_additional_modules": true,
"rules": [
{
"type": "ESModule",
"globs": "virtual:*",
"fallthrough": true
}
]
}
解決策3: カスタムesbuildプラグインの作成 ⭐
概要: esbuildプラグインで仮想モジュールを実ファイルに変換
onResolveフックでvirtual:react-router/server-buildを検出
onLoadフックで実ビルドファイルの内容を返す
解決策4: Viteプラグインによるビルド時変換 ⭐
概要: Viteプラグインで開発時と本番時の処理を分離
開発時: 仮想モジュールをそのまま使用
ビルド時: 実ファイルパスに自動変換
🛠 推奨実装プラン
フェーズ1: 即効性のある改善
1. wrangler.jsonc設定の調整を試行(最小リスク)
2. 動作しない場合はesbuildプラグインアプローチ
フェーズ2: 根本的解決
3. Cloudflare公式テンプレートへの移行を検討
4. 移行時のダウンタイム最小化戦略
フェーズ3: 最適化
5. 開発体験の向上
6. CI/CDパイプラインの改善
どのアプローチから試したいでしょうか?最もリスクが低く即効性があるのは解決策2のwrangler.jsonc設定です。
基素.icon1が確実なので1を実行していく
提案でこれを最優先にするのは自分の判断と合致
こういう定型作業はLLMの十八番!スイスイ進むがProだと2時間作業で3時間のrate limitとなる。この開発をずっとやりたいならProにしなければならなそう。Proだと上位モデルを使うだろうからトークン消費も増えて時間は変わらないのかもしれないが
⏺ 🎉 HAMPU統合完了レポート
重要な変更点
1. アーキテクチャの根本的変更
CircleCart: 独自React Router実装 + 問題のあるvirtual module解決
hampu-v3: Cloudflare公式React Router v7テンプレート
2. Virtual Module問題の完全解決
問題: Could not resolve "virtual:react-router/server-build"
以前: 複雑な環境分岐とファイル操作での回避策
現在: 公式テンプレートの標準実装で根本解決
3. 型システムの統一
以前: 分散した型定義 (~/routes/_index, 独自Env型)
現在: 統一型システム (workers/hampu-do.ts, Cloudflare自動生成型)
4. React Router v7対応
以前: import { useNavigate } from 'react-router-dom'
現在: import { useNavigate } from 'react-router'
5. テスト環境の完全統合
20/20テスト成功: BookItem(8) + useLongPress(8) + _index(4)
vitest + happy-dom + @testing-library完全対応
なぜ環境統合に成功できたのか
1. Cloudflare公式テンプレートの採用
$ npm create cloudflare@latest hampu-v3 -- --framework react-router
メリット: 既にvirtual module問題が解決済み
結果: ゼロからの複雑な設定不要
2. 段階的移行戦略
Phase 1: 基本設定 → Phase 2: コンポーネント → Phase 3: ルート
Phase 4: テスト環境 → Phase 5: スタイル → Phase 6: 全テスト
各段階でbuild/lint/typecheck確認
問題の早期発見と修正
3. 型システムの統一
4. CI/CD統合の実現
新しいリポジトリを作って実験
成功判定基準: npm run build && npm run lint 成功
5. React Router v7の自動型生成活用
code:js
// 自動生成された型を活用
import type { Route } from "./+types/home";
export function loader({ context }: Route.LoaderArgs)
丸っと作り直しは大成功。ビルドも目論見通り簡素化してファイル差し替え方式は廃止できた。
どうもLLMフランケンシュタインをしていたらビルドの設定が複雑になっていたようだ。しかしこれはGPT-5もリポジトリ上で修正はできなかった。新しいし、情報がないのだろう。
ADRを作成して意思決定のログを管理